{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/ljj/anaconda/envs/python3env/lib/python3.6/site-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.\n",
      "  \"This module will be removed in 0.20.\", DeprecationWarning)\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    " \n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn import preprocessing\n",
    "from sklearn.ensemble import RandomForestRegressor\n",
    "from sklearn.pipeline import make_pipeline\n",
    "from sklearn.model_selection import GridSearchCV\n",
    "from sklearn.metrics import mean_squared_error, r2_score\n",
    "from sklearn.externals import joblib \n",
    "from sklearn.ensemble import GradientBoostingRegressor\n",
    "from sklearn.feature_selection import SelectFromModel\n",
    "from sklearn.decomposition import PCA\n",
    "from sklearn.cross_validation import cross_val_score\n",
    "import matplotlib.pyplot as plt\n",
    "import xgboost as xgb\n",
    "from lightgbm import LGBMRegressor\n",
    "import math\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "height has been deprecated.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "pd.set_option('display.max_colwidth',1000)\n",
    "pd.set_option('display.height',1000)\n",
    "pd.set_option('display.max_rows',500)\n",
    "pd.set_option('display.max_columns',500)\n",
    "pd.set_option('display.width',1000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_data = pd.read_csv('./public.train.csv')\n",
    "test_data = pd.read_csv('./public.test.csv')\n",
    "submit = pd.read_csv('./submit_example.csv') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ID</th>\n",
       "      <th>板温</th>\n",
       "      <th>现场温度</th>\n",
       "      <th>光照强度</th>\n",
       "      <th>转换效率</th>\n",
       "      <th>转换效率A</th>\n",
       "      <th>转换效率B</th>\n",
       "      <th>转换效率C</th>\n",
       "      <th>电压A</th>\n",
       "      <th>电压B</th>\n",
       "      <th>电压C</th>\n",
       "      <th>电流A</th>\n",
       "      <th>电流B</th>\n",
       "      <th>电流C</th>\n",
       "      <th>功率A</th>\n",
       "      <th>功率B</th>\n",
       "      <th>功率C</th>\n",
       "      <th>平均功率</th>\n",
       "      <th>风速</th>\n",
       "      <th>风向</th>\n",
       "      <th>发电量</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "      <td>9000.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>9062.866444</td>\n",
       "      <td>6.703914</td>\n",
       "      <td>-0.629456</td>\n",
       "      <td>339.890222</td>\n",
       "      <td>64.077781</td>\n",
       "      <td>52.906926</td>\n",
       "      <td>84.416487</td>\n",
       "      <td>54.909988</td>\n",
       "      <td>717.852444</td>\n",
       "      <td>722.317556</td>\n",
       "      <td>700.171889</td>\n",
       "      <td>4.124878</td>\n",
       "      <td>4.647638</td>\n",
       "      <td>4.633024</td>\n",
       "      <td>3118.110127</td>\n",
       "      <td>3168.251196</td>\n",
       "      <td>3057.906246</td>\n",
       "      <td>3114.755833</td>\n",
       "      <td>2.356078</td>\n",
       "      <td>221.298556</td>\n",
       "      <td>5.695245</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>5114.232566</td>\n",
       "      <td>11.742366</td>\n",
       "      <td>67.430126</td>\n",
       "      <td>220.132765</td>\n",
       "      <td>807.424850</td>\n",
       "      <td>606.060373</td>\n",
       "      <td>2191.630414</td>\n",
       "      <td>705.950654</td>\n",
       "      <td>1931.338424</td>\n",
       "      <td>2048.559736</td>\n",
       "      <td>1674.291659</td>\n",
       "      <td>2.570927</td>\n",
       "      <td>18.083549</td>\n",
       "      <td>16.656423</td>\n",
       "      <td>13715.886085</td>\n",
       "      <td>14213.778780</td>\n",
       "      <td>11674.064480</td>\n",
       "      <td>7754.250793</td>\n",
       "      <td>1.629720</td>\n",
       "      <td>97.887963</td>\n",
       "      <td>3.463744</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>10.000000</td>\n",
       "      <td>-24.790000</td>\n",
       "      <td>-6321.700000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>-0.125144</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>4682.750000</td>\n",
       "      <td>-1.870000</td>\n",
       "      <td>-7.600000</td>\n",
       "      <td>153.000000</td>\n",
       "      <td>20.510000</td>\n",
       "      <td>20.460000</td>\n",
       "      <td>20.280000</td>\n",
       "      <td>20.580000</td>\n",
       "      <td>641.000000</td>\n",
       "      <td>638.000000</td>\n",
       "      <td>638.000000</td>\n",
       "      <td>1.740000</td>\n",
       "      <td>1.710000</td>\n",
       "      <td>1.800000</td>\n",
       "      <td>1192.230000</td>\n",
       "      <td>1159.305000</td>\n",
       "      <td>1223.982500</td>\n",
       "      <td>1219.855000</td>\n",
       "      <td>1.200000</td>\n",
       "      <td>152.000000</td>\n",
       "      <td>2.512812</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>9083.500000</td>\n",
       "      <td>5.640000</td>\n",
       "      <td>-2.400000</td>\n",
       "      <td>314.000000</td>\n",
       "      <td>25.230000</td>\n",
       "      <td>25.020000</td>\n",
       "      <td>25.015000</td>\n",
       "      <td>25.390000</td>\n",
       "      <td>669.000000</td>\n",
       "      <td>666.000000</td>\n",
       "      <td>666.000000</td>\n",
       "      <td>4.050000</td>\n",
       "      <td>4.120000</td>\n",
       "      <td>4.110000</td>\n",
       "      <td>2730.210000</td>\n",
       "      <td>2774.940000</td>\n",
       "      <td>2768.760000</td>\n",
       "      <td>2762.200000</td>\n",
       "      <td>2.200000</td>\n",
       "      <td>269.000000</td>\n",
       "      <td>5.769032</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>13470.000000</td>\n",
       "      <td>15.620000</td>\n",
       "      <td>8.100000</td>\n",
       "      <td>526.000000</td>\n",
       "      <td>37.190000</td>\n",
       "      <td>36.532500</td>\n",
       "      <td>36.972500</td>\n",
       "      <td>36.885000</td>\n",
       "      <td>689.000000</td>\n",
       "      <td>686.000000</td>\n",
       "      <td>686.000000</td>\n",
       "      <td>6.482500</td>\n",
       "      <td>6.530000</td>\n",
       "      <td>6.600000</td>\n",
       "      <td>4263.307500</td>\n",
       "      <td>4267.297500</td>\n",
       "      <td>4329.490000</td>\n",
       "      <td>4278.105000</td>\n",
       "      <td>3.300000</td>\n",
       "      <td>283.000000</td>\n",
       "      <td>8.896220</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>17876.000000</td>\n",
       "      <td>36.490000</td>\n",
       "      <td>78.700000</td>\n",
       "      <td>941.000000</td>\n",
       "      <td>60856.240000</td>\n",
       "      <td>27472.310000</td>\n",
       "      <td>178911.990000</td>\n",
       "      <td>41632.210000</td>\n",
       "      <td>65515.000000</td>\n",
       "      <td>65512.000000</td>\n",
       "      <td>65470.000000</td>\n",
       "      <td>9.430000</td>\n",
       "      <td>652.020000</td>\n",
       "      <td>647.620000</td>\n",
       "      <td>470096.580000</td>\n",
       "      <td>465945.500000</td>\n",
       "      <td>469844.840000</td>\n",
       "      <td>160151.370000</td>\n",
       "      <td>19.300000</td>\n",
       "      <td>672.000000</td>\n",
       "      <td>12.288756</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                 ID           板温         现场温度         光照强度          转换效率         转换效率A          转换效率B         转换效率C           电压A           电压B           电压C          电流A          电流B          电流C            功率A            功率B            功率C           平均功率           风速           风向          发电量\n",
       "count   9000.000000  9000.000000  9000.000000  9000.000000   9000.000000   9000.000000    9000.000000   9000.000000   9000.000000   9000.000000   9000.000000  9000.000000  9000.000000  9000.000000    9000.000000    9000.000000    9000.000000    9000.000000  9000.000000  9000.000000  9000.000000\n",
       "mean    9062.866444     6.703914    -0.629456   339.890222     64.077781     52.906926      84.416487     54.909988    717.852444    722.317556    700.171889     4.124878     4.647638     4.633024    3118.110127    3168.251196    3057.906246    3114.755833     2.356078   221.298556     5.695245\n",
       "std     5114.232566    11.742366    67.430126   220.132765    807.424850    606.060373    2191.630414    705.950654   1931.338424   2048.559736   1674.291659     2.570927    18.083549    16.656423   13715.886085   14213.778780   11674.064480    7754.250793     1.629720    97.887963     3.463744\n",
       "min       10.000000   -24.790000 -6321.700000     0.000000      0.000000      0.000000       0.000000      0.000000      0.000000      0.000000      0.000000     0.000000     0.000000     0.000000       0.000000       0.000000       0.000000       0.000000     0.000000     0.000000    -0.125144\n",
       "25%     4682.750000    -1.870000    -7.600000   153.000000     20.510000     20.460000      20.280000     20.580000    641.000000    638.000000    638.000000     1.740000     1.710000     1.800000    1192.230000    1159.305000    1223.982500    1219.855000     1.200000   152.000000     2.512812\n",
       "50%     9083.500000     5.640000    -2.400000   314.000000     25.230000     25.020000      25.015000     25.390000    669.000000    666.000000    666.000000     4.050000     4.120000     4.110000    2730.210000    2774.940000    2768.760000    2762.200000     2.200000   269.000000     5.769032\n",
       "75%    13470.000000    15.620000     8.100000   526.000000     37.190000     36.532500      36.972500     36.885000    689.000000    686.000000    686.000000     6.482500     6.530000     6.600000    4263.307500    4267.297500    4329.490000    4278.105000     3.300000   283.000000     8.896220\n",
       "max    17876.000000    36.490000    78.700000   941.000000  60856.240000  27472.310000  178911.990000  41632.210000  65515.000000  65512.000000  65470.000000     9.430000   652.020000   647.620000  470096.580000  465945.500000  469844.840000  160151.370000    19.300000   672.000000    12.288756"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ID</th>\n",
       "      <th>板温</th>\n",
       "      <th>现场温度</th>\n",
       "      <th>光照强度</th>\n",
       "      <th>转换效率</th>\n",
       "      <th>转换效率A</th>\n",
       "      <th>转换效率B</th>\n",
       "      <th>转换效率C</th>\n",
       "      <th>电压A</th>\n",
       "      <th>电压B</th>\n",
       "      <th>电压C</th>\n",
       "      <th>电流A</th>\n",
       "      <th>电流B</th>\n",
       "      <th>电流C</th>\n",
       "      <th>功率A</th>\n",
       "      <th>功率B</th>\n",
       "      <th>功率C</th>\n",
       "      <th>平均功率</th>\n",
       "      <th>风速</th>\n",
       "      <th>风向</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "      <td>8409.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>9134.017362</td>\n",
       "      <td>6.743565</td>\n",
       "      <td>-0.532370</td>\n",
       "      <td>340.494232</td>\n",
       "      <td>67.180684</td>\n",
       "      <td>61.592292</td>\n",
       "      <td>71.052603</td>\n",
       "      <td>68.897216</td>\n",
       "      <td>692.506243</td>\n",
       "      <td>759.009989</td>\n",
       "      <td>712.268284</td>\n",
       "      <td>4.120589</td>\n",
       "      <td>4.457701</td>\n",
       "      <td>4.903527</td>\n",
       "      <td>2891.299515</td>\n",
       "      <td>3396.516889</td>\n",
       "      <td>3131.409281</td>\n",
       "      <td>3139.741955</td>\n",
       "      <td>2.391366</td>\n",
       "      <td>223.006422</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>5135.024213</td>\n",
       "      <td>11.733794</td>\n",
       "      <td>70.730474</td>\n",
       "      <td>220.139546</td>\n",
       "      <td>927.594047</td>\n",
       "      <td>2022.687363</td>\n",
       "      <td>1311.881379</td>\n",
       "      <td>1350.963592</td>\n",
       "      <td>1413.713947</td>\n",
       "      <td>2545.796157</td>\n",
       "      <td>1870.362932</td>\n",
       "      <td>2.570118</td>\n",
       "      <td>14.264229</td>\n",
       "      <td>21.105298</td>\n",
       "      <td>8837.131405</td>\n",
       "      <td>17642.610316</td>\n",
       "      <td>12662.028495</td>\n",
       "      <td>7941.118597</td>\n",
       "      <td>1.646400</td>\n",
       "      <td>96.326689</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>1.000000</td>\n",
       "      <td>-23.890000</td>\n",
       "      <td>-6414.200000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>0.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>4732.000000</td>\n",
       "      <td>-1.790000</td>\n",
       "      <td>-7.500000</td>\n",
       "      <td>155.000000</td>\n",
       "      <td>20.400000</td>\n",
       "      <td>20.380000</td>\n",
       "      <td>20.220000</td>\n",
       "      <td>20.530000</td>\n",
       "      <td>641.000000</td>\n",
       "      <td>638.000000</td>\n",
       "      <td>637.000000</td>\n",
       "      <td>1.740000</td>\n",
       "      <td>1.750000</td>\n",
       "      <td>1.810000</td>\n",
       "      <td>1181.040000</td>\n",
       "      <td>1176.600000</td>\n",
       "      <td>1233.690000</td>\n",
       "      <td>1225.620000</td>\n",
       "      <td>1.200000</td>\n",
       "      <td>167.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>9262.000000</td>\n",
       "      <td>5.560000</td>\n",
       "      <td>-2.300000</td>\n",
       "      <td>312.000000</td>\n",
       "      <td>25.060000</td>\n",
       "      <td>24.770000</td>\n",
       "      <td>24.800000</td>\n",
       "      <td>25.380000</td>\n",
       "      <td>668.000000</td>\n",
       "      <td>666.000000</td>\n",
       "      <td>666.000000</td>\n",
       "      <td>4.040000</td>\n",
       "      <td>4.130000</td>\n",
       "      <td>4.100000</td>\n",
       "      <td>2710.500000</td>\n",
       "      <td>2762.540000</td>\n",
       "      <td>2756.000000</td>\n",
       "      <td>2739.600000</td>\n",
       "      <td>2.200000</td>\n",
       "      <td>269.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>13576.000000</td>\n",
       "      <td>15.470000</td>\n",
       "      <td>8.300000</td>\n",
       "      <td>529.000000</td>\n",
       "      <td>36.960000</td>\n",
       "      <td>36.060000</td>\n",
       "      <td>36.630000</td>\n",
       "      <td>36.930000</td>\n",
       "      <td>689.000000</td>\n",
       "      <td>686.000000</td>\n",
       "      <td>686.000000</td>\n",
       "      <td>6.470000</td>\n",
       "      <td>6.530000</td>\n",
       "      <td>6.610000</td>\n",
       "      <td>4245.750000</td>\n",
       "      <td>4262.500000</td>\n",
       "      <td>4324.900000</td>\n",
       "      <td>4268.160000</td>\n",
       "      <td>3.300000</td>\n",
       "      <td>283.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>17875.000000</td>\n",
       "      <td>36.800000</td>\n",
       "      <td>54.500000</td>\n",
       "      <td>934.000000</td>\n",
       "      <td>61448.540000</td>\n",
       "      <td>183289.380000</td>\n",
       "      <td>86857.130000</td>\n",
       "      <td>77396.680000</td>\n",
       "      <td>65477.000000</td>\n",
       "      <td>65508.000000</td>\n",
       "      <td>65514.000000</td>\n",
       "      <td>9.570000</td>\n",
       "      <td>653.710000</td>\n",
       "      <td>652.040000</td>\n",
       "      <td>453360.600000</td>\n",
       "      <td>603301.050000</td>\n",
       "      <td>458325.000000</td>\n",
       "      <td>202906.540000</td>\n",
       "      <td>25.200000</td>\n",
       "      <td>619.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                 ID           板温         现场温度         光照强度          转换效率          转换效率A         转换效率B         转换效率C           电压A           电压B           电压C          电流A          电流B          电流C            功率A            功率B            功率C           平均功率           风速           风向\n",
       "count   8409.000000  8409.000000  8409.000000  8409.000000   8409.000000    8409.000000   8409.000000   8409.000000   8409.000000   8409.000000   8409.000000  8409.000000  8409.000000  8409.000000    8409.000000    8409.000000    8409.000000    8409.000000  8409.000000  8409.000000\n",
       "mean    9134.017362     6.743565    -0.532370   340.494232     67.180684      61.592292     71.052603     68.897216    692.506243    759.009989    712.268284     4.120589     4.457701     4.903527    2891.299515    3396.516889    3131.409281    3139.741955     2.391366   223.006422\n",
       "std     5135.024213    11.733794    70.730474   220.139546    927.594047    2022.687363   1311.881379   1350.963592   1413.713947   2545.796157   1870.362932     2.570118    14.264229    21.105298    8837.131405   17642.610316   12662.028495    7941.118597     1.646400    96.326689\n",
       "min        1.000000   -23.890000 -6414.200000     0.000000      0.000000       0.000000      0.000000      0.000000      0.000000      0.000000      0.000000     0.000000     0.000000     0.000000       0.000000       0.000000       0.000000       0.000000     0.000000     0.000000\n",
       "25%     4732.000000    -1.790000    -7.500000   155.000000     20.400000      20.380000     20.220000     20.530000    641.000000    638.000000    637.000000     1.740000     1.750000     1.810000    1181.040000    1176.600000    1233.690000    1225.620000     1.200000   167.000000\n",
       "50%     9262.000000     5.560000    -2.300000   312.000000     25.060000      24.770000     24.800000     25.380000    668.000000    666.000000    666.000000     4.040000     4.130000     4.100000    2710.500000    2762.540000    2756.000000    2739.600000     2.200000   269.000000\n",
       "75%    13576.000000    15.470000     8.300000   529.000000     36.960000      36.060000     36.630000     36.930000    689.000000    686.000000    686.000000     6.470000     6.530000     6.610000    4245.750000    4262.500000    4324.900000    4268.160000     3.300000   283.000000\n",
       "max    17875.000000    36.800000    54.500000   934.000000  61448.540000  183289.380000  86857.130000  77396.680000  65477.000000  65508.000000  65514.000000     9.570000   653.710000   652.040000  453360.600000  603301.050000  458325.000000  202906.540000    25.200000   619.000000"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_data.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# print(test_data[test_data['现场温度'] < -274])\n",
    "# print('\\n',train_data[train_data['现场温度'] < -274])\n",
    "# print('\\n',test_data['风向'][test_data['风向'] > 360])\n",
    "# print('\\n',train_data['风向'][train_data['风向'] > 360])\n",
    "# len(np.unique(test_data['风向']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def drop_col(df, col_name):\n",
    "    return df.drop([col_name], axis=1)\n",
    "\n",
    "# def drop_outlayer(df):\n",
    "#     df.drop(df[df['发电量'] < 0].index, inplace=True)\n",
    "#     df.drop(df[df['现场温度'] < -268].index, inplace=True)\n",
    "#     df.drop(df[df['转换效率'] > 20000].index, inplace=True)\n",
    "#     df.drop(df[df['转换效率'] < 0].index, inplace=True)\n",
    "#     df.drop(df[df['风向'] > 360].index, inplace=True)\n",
    "#     return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# train_data = drop_outlayer(train_data)\n",
    "\n",
    "# train_data = drop_col(train_data, '平均功率')\n",
    "# train_data = drop_col(train_data, '转换效率')\n",
    "# test_data = drop_col(test_data, '平均功率')\n",
    "# test_data = drop_col(test_data, '转换效率')\n",
    "# train_data = drop_col(train_data, '风速')\n",
    "# test_data = drop_col(test_data, '风速')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 去除重复值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "train_data.drop_duplicates(train_data.columns.drop('ID'), keep='first', inplace=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 处理缺失值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1. 平均值、众数替换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def process_missing_value(df, feature, mode='mean'):\n",
    "    if mode.lower() == 'mean':\n",
    "        df[feature].loc[(df[feature] == 0) | (df[feature] == 0.)] = df[feature].mean()\n",
    "    elif model.lower() == 'mode':\n",
    "        df[feature].loc[(df[feature] == 0) | (df[feature] == 0.)] = df[feature].mode()\n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def col_missing_count(df, feature):\n",
    "    return df[feature][(df[feature] == 0.) | (df[feature] == 0)].count()\n",
    "\n",
    "def show_all_missing_value(df, process=False, mode='mean'): \n",
    "    missing_count = {}\n",
    "    for f in df.columns.drop(['ID']):\n",
    "        missing_count[f] = [col_missing_count(df, f)]\n",
    "\n",
    "    missing = pd.DataFrame(missing_count)\n",
    "    if process:\n",
    "        for f in df.columns.drop(['ID']):\n",
    "            df = process_missing_value(df, f, mode=mode)\n",
    "    return missing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# show_all_missing_value(train_data, process=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# show_all_missing_value(train_data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. 近邻值替换"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "NearestNeighbors(algorithm='auto', leaf_size=30, metric='cosine',\n",
       "         metric_params=None, n_jobs=8, n_neighbors=5, p=2, radius=1.0)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.neighbors import NearestNeighbors\n",
    "neighbors = NearestNeighbors(metric='cosine', n_jobs=8, algorithm='auto')\n",
    "neighbors.fit(train_data.drop(['ID', '发电量'], axis=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def process_missing_by_nearest_neighbors(df):\n",
    "    if '发电量' in df.columns:\n",
    "        tmp_df = df.drop(['ID', '发电量'], axis=1)\n",
    "    else:\n",
    "        tmp_df = df.drop(['ID'], axis=1)\n",
    "    for idx, line in tmp_df.iterrows():\n",
    "        if (line[(line == 0) | (line == 0.)].count() > 0):\n",
    "            col_index = line[(line == 0) | (line == 0.)].index\n",
    "            n_index = neighbors.kneighbors(line.values.reshape(1, -1))[1][0]\n",
    "            df.loc[idx, col_index] = np.average(df.loc[n_index.tolist(), col_index].dropna(), axis=0)    \n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "# trian_data = process_missing_by_nearest_neighbors(train_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# test_data = process_missing_by_nearest_neighbors(test_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "# show_all_missing_value(train_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "# show_all_missing_value(test_data)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据分布调整（没什么用）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[<matplotlib.axes._subplots.AxesSubplot object at 0x11c24a240>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11c8ce390>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11c230908>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x10b1d32b0>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11c7f1d30>],\n",
       "       [<matplotlib.axes._subplots.AxesSubplot object at 0x11c7f1d68>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11c863a90>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11c890780>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11c928860>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11cc60fd0>],\n",
       "       [<matplotlib.axes._subplots.AxesSubplot object at 0x11ccb5fd0>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11cc8e518>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11c226358>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d34d128>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d387128>],\n",
       "       [<matplotlib.axes._subplots.AxesSubplot object at 0x11d3bd668>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d3e4c18>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d420ba8>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d459ba8>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d49c128>],\n",
       "       [<matplotlib.axes._subplots.AxesSubplot object at 0x11d4a40f0>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d5006d8>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d5386d8>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d571c18>,\n",
       "        <matplotlib.axes._subplots.AxesSubplot object at 0x11d5a6c18>]],\n",
       "      dtype=object)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n/wW+ztMoOQK/VwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x11c232b70>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_data.hist(figsize=(15,13))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ID        5114.321777\n",
       "板温          11.774257\n",
       "现场温度        67.738640\n",
       "光照强度       218.944451\n",
       "转换效率       811.108515\n",
       "转换效率A      608.822482\n",
       "转换效率B     2201.671023\n",
       "转换效率C      709.172324\n",
       "电压A       1939.190689\n",
       "电压B       2056.995210\n",
       "电压C       1680.867181\n",
       "电流A          2.554991\n",
       "电流B         18.161688\n",
       "电流C         16.727608\n",
       "功率A      13775.968549\n",
       "功率B      14276.168783\n",
       "功率C      11724.393268\n",
       "平均功率      7784.811640\n",
       "风速           1.624018\n",
       "风向          96.370203\n",
       "发电量          3.445110\n",
       "dtype: float64"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_data.std()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "def process_hugstd_value(df, feature, method='sqrt'):\n",
    "    if method == 'sqrt':\n",
    "        df[feature] = df[feature].apply(np.sqrt)\n",
    "    elif method == 'log':\n",
    "        df[feature] = df[feature].apply(np.log)\n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# train_data = process_hugstd_value(train_data, '转换效率B')\n",
    "# test_data = process_hugstd_value(test_data, '转换效率B')\n",
    "\n",
    "# train_data = process_hugstd_value(train_data, '电压A')\n",
    "# test_data = process_hugstd_value(test_data, '电压A')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "# train_data.describe()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 风向值离散化（没什么用）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "def discrete(x):\n",
    "    if x % 10 >= 5:\n",
    "        x //= 10\n",
    "        x *= 10\n",
    "        x += 10\n",
    "    else:\n",
    "        x //= 10\n",
    "        x *= 10\n",
    "    return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# train_data['风向'] = train_data['风向'].apply(discrete)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "# train_data['风向'].plot(kind='hist')\n",
    "# plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "# len(np.unique(train_data['风向']))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model: Xgboost, Sklearn_GBDT, RandomForest, LightGBM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_train_data(train_data, test_data, poly=False, select=False):\n",
    "    y = train_data['发电量']\n",
    "    X = train_data.drop(['发电量','ID'], axis=1)\n",
    "    sub_data = test_data.drop(['ID'], axis=1)\n",
    "\n",
    "    if poly:\n",
    "        from sklearn.preprocessing import PolynomialFeatures\n",
    "        poly = PolynomialFeatures(degree=2, interaction_only=True)\n",
    "        X = poly.fit_transform(X)\n",
    "        sub_data = poly.transform(sub_data)\n",
    "        \n",
    "    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=123)\n",
    "\n",
    "    if select:\n",
    "        from sklearn.feature_selection import SelectFromModel\n",
    "        sm = SelectFromModel(GradientBoostingRegressor(random_state=2))\n",
    "        X_train = sm.fit_transform(X_train, y_train)\n",
    "        X_test = sm.transform(X_test)\n",
    "        sub_data = sm.transform(sub_data)\n",
    "        \n",
    "    return X_train, X_test, y_train, y_test, sub_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def cal_score(mse):\n",
    "    return 1 / (1 + math.sqrt(mse))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(7134, 54) (8409, 54)\n"
     ]
    }
   ],
   "source": [
    "X_train, X_test, y_train, y_test, sub_data = generate_train_data(train_data, test_data, poly=True, select=True)\n",
    "print(X_train.shape, sub_data.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "xgbt = xgb.XGBRegressor(n_estimators=200, max_depth=3, random_state=1, n_jobs=8)\n",
    "gbdt = GradientBoostingRegressor(n_estimators=200, max_depth=3, max_features='log2', random_state=1)\n",
    "forest = RandomForestRegressor(n_estimators=100, max_features='log2', random_state=1, n_jobs=8)\n",
    "\n",
    "lgb_params = {}\n",
    "lgb_params['n_estimators'] = 200\n",
    "lgb_params['max_depth'] = 3 \n",
    "lgb_params['random_state'] = 1\n",
    "lgb = LGBMRegressor(**lgb_params)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def train(X_train, y_train):\n",
    "    xgbt.fit(X_train, y_train)\n",
    "    gbdt.fit(X_train, y_train)\n",
    "    forest.fit(X_train, y_train)\n",
    "    lgb.fit(X_train, y_train)\n",
    "\n",
    "def predict(X_test, y_test):\n",
    "    y_pred_xgb = xgbt.predict(X_test)\n",
    "    mse_xgb = mean_squared_error(y_test.values, y_pred_xgb)\n",
    "    \n",
    "    y_pred_gbdt = gbdt.predict(X_test)\n",
    "    mse_gbdt = mean_squared_error(y_test.values, y_pred_gbdt)\n",
    "    \n",
    "    y_pred_forest = forest.predict(X_test)\n",
    "    mse_forest = mean_squared_error(y_true=y_test, y_pred=y_pred_forest)\n",
    "    \n",
    "    y_pred_lgb = lgb.predict(X_test)\n",
    "    mse_lgb = mean_squared_error(y_true=y_test, y_pred=y_pred_lgb)\n",
    "    \n",
    "    res = pd.DataFrame()\n",
    "    res['model'] = np.array(['XGBoost', 'Sklearn_GBDT', 'RandomForest', 'LightGBM'])\n",
    "    res['mse'] = np.array([mse_xgb, mse_gbdt, mse_forest, mse_lgb])\n",
    "    res['score'] = np.array([cal_score(mse_xgb), cal_score(mse_gbdt), cal_score(mse_forest), cal_score(mse_lgb)])\n",
    "    return res\n",
    "\n",
    "def cross_validation_using_mse(X_train, y_train, cv=5):\n",
    "    scores_xgb = cross_val_score(xgbt, X_train, y_train, cv=cv, scoring='neg_mean_squared_error')\n",
    "    xgb_avg = np.average(-scores_xgb)\n",
    "    print('Average XGB - MSE:', xgb_avg, ' - Score:', cal_score(xgb_avg))\n",
    "    \n",
    "    scores_gbdt = cross_val_score(gbdt, X_train, y_train, cv=cv, scoring='neg_mean_squared_error')\n",
    "    gbdt_avg = np.average(-scores_gbdt)\n",
    "    print('Average GBDT - MSE:', gbdt_avg, ' - Score:', cal_score(gbdt_avg))\n",
    "    \n",
    "    scores_forest = cross_val_score(forest, X_train, y_train, cv=cv, scoring='neg_mean_squared_error')\n",
    "    rf_avg = np.average(-scores_forest)\n",
    "    print('Average RF - MSE:', rf_avg, ' - Score:', cal_score(rf_avg))\n",
    "    \n",
    "    scores_lgb = cross_val_score(lgb, X_train, y_train, cv=cv, scoring='neg_mean_squared_error')\n",
    "    lgb_avg = np.average(-scores_lgb)\n",
    "    print('Average LGB - MSE:', lgb_avg, ' - Score:', cal_score(lgb_avg))\n",
    "    \n",
    "    res = pd.DataFrame({\n",
    "        'XGBoost': -scores_xgb,\n",
    "        'Skleanr_GBDT': -scores_gbdt,\n",
    "        'RandomForest': -scores_forest,\n",
    "        'LightGBM': -scores_lgb\n",
    "    })\n",
    "    \n",
    "    return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>model</th>\n",
       "      <th>mse</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>XGBoost</td>\n",
       "      <td>0.018279</td>\n",
       "      <td>0.880903</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Sklearn_GBDT</td>\n",
       "      <td>0.021172</td>\n",
       "      <td>0.872976</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>RandomForest</td>\n",
       "      <td>0.016943</td>\n",
       "      <td>0.884825</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>LightGBM</td>\n",
       "      <td>0.017924</td>\n",
       "      <td>0.881926</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          model       mse     score\n",
       "0       XGBoost  0.018279  0.880903\n",
       "1  Sklearn_GBDT  0.021172  0.872976\n",
       "2  RandomForest  0.016943  0.884825\n",
       "3      LightGBM  0.017924  0.881926"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train(X_train, y_train)\n",
    "predict(X_test, y_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Average XGB - MSE: 0.03544693597776803  - Score: 0.8415570520881192\n",
      "Average GBDT - MSE: 0.03864388004656939  - Score: 0.8357147951953262\n",
      "Average RF - MSE: 0.03666179797449355  - Score: 0.8392974452052131\n",
      "Average LGB - MSE: 0.03647621965487698  - Score: 0.8396393850421255\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>LightGBM</th>\n",
       "      <th>RandomForest</th>\n",
       "      <th>Skleanr_GBDT</th>\n",
       "      <th>XGBoost</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.015751</td>\n",
       "      <td>0.015402</td>\n",
       "      <td>0.016909</td>\n",
       "      <td>0.013968</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.031325</td>\n",
       "      <td>0.032829</td>\n",
       "      <td>0.033047</td>\n",
       "      <td>0.028023</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0.024215</td>\n",
       "      <td>0.026430</td>\n",
       "      <td>0.024570</td>\n",
       "      <td>0.023745</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0.092499</td>\n",
       "      <td>0.091797</td>\n",
       "      <td>0.097578</td>\n",
       "      <td>0.093750</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0.018591</td>\n",
       "      <td>0.016851</td>\n",
       "      <td>0.021115</td>\n",
       "      <td>0.017749</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   LightGBM  RandomForest  Skleanr_GBDT   XGBoost\n",
       "0  0.015751      0.015402      0.016909  0.013968\n",
       "1  0.031325      0.032829      0.033047  0.028023\n",
       "2  0.024215      0.026430      0.024570  0.023745\n",
       "3  0.092499      0.091797      0.097578  0.093750\n",
       "4  0.018591      0.016851      0.021115  0.017749"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cross_validation_using_mse(np.concatenate([X_train, X_test]), np.concatenate([y_train, y_test]), cv=5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Dropout\n",
    "from keras.callbacks import ModelCheckpoint\n",
    "from sklearn.preprocessing import MinMaxScaler\n",
    "from sklearn.preprocessing import PolynomialFeatures"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "min_max_scaler = MinMaxScaler()\n",
    "X_nn = min_max_scaler.fit_transform(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "poly = PolynomialFeatures(degree=2, interaction_only=True)\n",
    "X_nn = poly.fit_transform(X_nn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "NN = Sequential()\n",
    "NN.add(Dense(50, input_dim=X_nn.shape[1], init='uniform', activation='relu'))\n",
    "NN.add(Dropout(0.5, input_shape=(100, )))\n",
    "NN.add(Dense(50, init='uniform', activation='relu'))\n",
    "NN.add(Dense(1, init='uniform', activation='relu'))\n",
    "NN.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "NN.compile(loss='mse', optimizer='Adam', metrics=['mse'])\n",
    "NN.fit(x=X_nn, y=y_train, epochs=200)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "X_test_nn = min_max_scaler.transform(X_test)\n",
    "X_test_nn = poly.transform(X_test_nn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "y_pred_nn = NN.predict(X_test_nn)\n",
    "mean_squared_error(y_test, y_pred_nn)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_result = pd.DataFrame()\n",
    "df_result['ID'] = list(test_data['ID'])\n",
    "\n",
    "def output(sub_data, model='gbdt'):\n",
    "    if model == 'nn':\n",
    "        sub_data_nn = min_max_scaler.transform(np.array(sub_data))\n",
    "        sub_data_nn = poly.transform(sub_data_nn)\n",
    "        pred = NN.predict(sub_data_nn)\n",
    "\n",
    "    elif model == 'gbdt':\n",
    "        pred = gbdt.predict(sub_data)\n",
    "\n",
    "    elif model == 'xgb':\n",
    "        pred = xgbt.predict(sub_data)\n",
    "\n",
    "    elif model == 'rf':\n",
    "        pred = forest.predict(sub_data)\n",
    "    \n",
    "    elif model == 'lgb':\n",
    "        pred = lgb.predict(sub_data)\n",
    "        \n",
    "    return pred"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_result['score'] = output(sub_data, 'rf')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "df_result.to_csv('submit_rf_withpoly_withselectbygbdt_dropdup.csv', index=False, header=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
